package com.mt.roll.wms.dispatch.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mt.roll.core.base.BaseService;
import com.mt.roll.core.dal.entity.*;
import com.mt.roll.core.dal.service.*;
import com.mt.roll.core.params.IdParam;
import com.mt.roll.core.vo.R;
import com.mt.roll.process.params.ProcessFlowEquipmentQueryParam;
import com.mt.roll.process.service.ProcessFlowEquipmentService;
import com.mt.roll.process.vo.WorkSequenceEquipmentVo;
import com.mt.roll.wms.dispatch.LocalDisPatchService;
import com.mt.roll.wms.dispatch.constant.QGSConstant;
import com.mt.roll.wms.dispatch.taskPool.entity.CallRgvEntity;
import com.mt.roll.wms.dispatch.taskPool.entity.RgvBackInfo;
import com.mt.roll.wms.mapper.StorageLocationMapper;
import com.mt.roll.wms.utils.SnowflakeId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
public class LocalDispatchServiceImpl extends BaseService implements LocalDisPatchService {
    @Resource
    private StorageBoxCircInfoServiceBiz storageBoxCircInfoServiceBiz;

    @Resource
    private LocationStorageSubServiceBiz locationStorageSubServiceBiz;

    @Resource
    private StorageBoxCircInfoHisServiceBiz storageBoxCircInfoHisServiceBiz;

    @Resource
    private WorkOrderServiceBiz workOrderServiceBiz;

    @Autowired
    private ProcessFlowEquipmentService processFlowEquipmentService;

    @Resource
    private StorageLocationMapper storageLocationMapper;

    @Resource
    private LocationServiceBiz locationServiceBiz;

    @Resource
    private CarTaskExecutionInfoServiceBiz carTaskExecutionInfoServiceBiz;

    @Resource
    private CarTaskExecutionInfoHisServiceBiz carTaskExecutionInfoHisServiceBiz;


    @Override
    public Integer locationEmpty(IdParam idParam, List<LocationStorageSub> subList) {
        //修改存储箱状态为空
        //传进来的是location表的locationNumber，需要找到对应id
        StorageBoxCircInfo storageBoxCircInfo = getTsbciByLocationNo(idParam);
//        StorageBoxCircInfo storageBoxCircInfo = storageBoxCircInfoServiceBiz.getById(idParam.getId());
        StorageBoxCircInfo updateStorageBoxCircInfo = new StorageBoxCircInfo();
        BeanUtils.copyProperties(storageBoxCircInfo, updateStorageBoxCircInfo);
        updateStorageBoxCircInfo.setIsEmpty(0);
        LocalDateTime localDateTime = LocalDateTime.now();
        updateStorageBoxCircInfo.setUpdateTime(localDateTime);
        storageBoxCircInfoServiceBiz.updateById(updateStorageBoxCircInfo);

        //从缓存区取满箱
        //根据上下片，操作不同
        idParam.setId(storageBoxCircInfo.getId());
        Integer result = getSubstrateFromBuffer(idParam);
        //根据传的基板id，来更新需要操作的基板
        //基板需要获取更新后的标识
        StorageBoxCircInfo newStorageBoxCircInfo = storageBoxCircInfoServiceBiz.getById(idParam.getId());
        for (LocationStorageSub sub : subList){
//            sub.setStatus(0);
//            sub.setCode(String.valueOf(System.currentTimeMillis()));
            //插入的是库位上的当前编码
            sub.setLocationStorageSubId(newStorageBoxCircInfo.getLocationStorageSubId());
            sub.setLocationId(newStorageBoxCircInfo.getCurrLocationId());
            sub.setStorageId(newStorageBoxCircInfo.getStorageBoxId());
            sub.setSubType(1);
            //插入基板表
            locationStorageSubServiceBiz.save(sub);
        }
        return result;
    }

    @Override
    public Integer getSubstrateFromBuffer(IdParam idParam) {
        StorageBoxCircInfo storageBoxCircInfo = storageBoxCircInfoServiceBiz.getById(idParam.getId());
        String localProcess = storageBoxCircInfo.getInProcessCode();
        //查表获取缓冲区的箱子，取第一个，时间排序，先进先出
        List<StorageBoxCircInfo> bufferList = storageLocationMapper.getBufferBoxs(localProcess,2L,1);
        StorageBoxCircInfo bufferCircInfo;
        if (bufferList.size()!=0){
            bufferCircInfo = bufferList.get(0);
        }else {
            //缓冲区无满箱
            throw new RuntimeException("缓冲区无满箱");
        }
        //调WCS接口
        Long processLocationID = storageBoxCircInfo.getCurrLocationId();
        Location processLocation = locationServiceBiz.getById(processLocationID);
        if (processLocation==null){
            throw new RuntimeException("无库位id对应库位");
        }
        Integer processLocationNo = processLocation.getLocationNumber();
        Long bufferLocationID = bufferCircInfo.getCurrLocationId();
        Location bufferLocation = locationServiceBiz.getById(bufferLocationID);
        if (processLocation==null){
            throw new RuntimeException("无库位id对应库位");
        }
        Integer bufferLocationNo = bufferLocation.getLocationNumber();
        //RGV执行前的插入
        CarTaskExecutionInfo carTaskExecutionInfo = addCarTask(storageBoxCircInfo,bufferCircInfo,processLocation,bufferLocation);
        //调用RGV
        CallRgvEntity callRgvEntity = new CallRgvEntity();
        callRgvEntity.setStartLocationNum(processLocationNo);
        callRgvEntity.setEndLocationNum(bufferLocationNo);
        String returnMsg;
        try {
            returnMsg = callAgv(callRgvEntity);
        }catch (Exception e){
            throw new RuntimeException("RGV异常");
        }
        //防止出错后继续
        if (Integer.valueOf(returnMsg)!=1){
            return Integer.valueOf(returnMsg);
        }
        //RGV执行完的更新
        updateCarTaskExecutionInfo(carTaskExecutionInfo);
        Boolean exChangeResult = exChange(storageBoxCircInfo,bufferCircInfo,2);
        if (!exChangeResult){
            throw new RuntimeException("交换操作失败");
        }
        return Integer.parseInt(returnMsg);
    }

    @Override
    public Integer locationFull(IdParam idParam, List<LocationStorageSub> subList) {
        //修改存储箱状态为空
        //传进来的是location表的locationNumber，需要找到对应id
        StorageBoxCircInfo storageBoxCircInfo = getTsbciByLocationNo(idParam);
//        StorageBoxCircInfo storageBoxCircInfo = storageBoxCircInfoServiceBiz.getById(idParam.getId());
        StorageBoxCircInfo updateStorageBoxCircInfo = new StorageBoxCircInfo();
        BeanUtils.copyProperties(storageBoxCircInfo, updateStorageBoxCircInfo);
        updateStorageBoxCircInfo.setIsEmpty(1);
        //去工单表找到下一个工序
        String workOrderNo = storageBoxCircInfo.getWorkOrderNo();
        QueryWrapper workOrderWrapper = new QueryWrapper<>();
        workOrderWrapper.eq(WorkOrder.WORK_ORDER_NO,workOrderNo);
        WorkOrder workOrder = workOrderServiceBiz.getOne(workOrderWrapper);
        Long processFlowID = workOrder.getProcessId();
        ProcessFlowEquipmentQueryParam processFlowEquipmentQueryParam = new ProcessFlowEquipmentQueryParam();
        processFlowEquipmentQueryParam.setProcessFlowId(processFlowID);
        R<List<WorkSequenceEquipmentVo>> workSequences =  processFlowEquipmentService.list(processFlowEquipmentQueryParam);
        List<WorkSequenceEquipmentVo> workSequenceEquipmentVoList = workSequences.getData();

        int index=0;
        for (int i=0;i<workSequenceEquipmentVoList.size();i++){
            if (workSequenceEquipmentVoList.get(i).getWorkSequenceId().equals(storageBoxCircInfo.getInProcessCode())){
                index=i;
            }
        }
        if (index==workSequenceEquipmentVoList.size()){
            //TODO:如果为最后一道工序？

        }
        Long nextprocessFlowID = workSequenceEquipmentVoList.get(index+1).getWorkSequenceId();
        updateStorageBoxCircInfo.setNextProcessCode(nextprocessFlowID.toString());
        LocalDateTime localDateTime = LocalDateTime.now();
        updateStorageBoxCircInfo.setUpdateTime(localDateTime);
        storageBoxCircInfoServiceBiz.updateById(updateStorageBoxCircInfo);
        //根据传的基板id，来更新需要操作的基板
        for (LocationStorageSub sub : subList){
//            sub.setStatus(0);
//            sub.setCode(String.valueOf(System.currentTimeMillis()));
            //插入的是库位上的当前编码
            sub.setLocationStorageSubId(storageBoxCircInfo.getLocationStorageSubId());
            sub.setLocationId(storageBoxCircInfo.getCurrLocationId());
            sub.setStorageId(storageBoxCircInfo.getStorageBoxId());
            sub.setSubType(1);
            //插入基板表
            locationStorageSubServiceBiz.save(sub);
        }
        //从缓冲区取空箱
        idParam.setId(storageBoxCircInfo.getId());
        Integer result = getEmptyBoxFromBuffer(idParam);
        return result;
    }

    private String callAgv(CallRgvEntity callRgvEntity) throws IOException {
        String result= HttpUtil.post(QGSConstant.CallRgv1Url, JSONObject.toJSONString(callRgvEntity));
        ObjectMapper objectMapper = new ObjectMapper();
        RgvBackInfo rgvBackInfo = objectMapper.readValue(result.getBytes(), RgvBackInfo.class);
        return rgvBackInfo.getMsg();
    }

    @Override
    public Integer getEmptyBoxFromBuffer(IdParam idParam) {
        //获取下一道工序和缓冲区位置
        StorageBoxCircInfo storageBoxCircInfo = storageBoxCircInfoServiceBiz.getById(idParam.getId());
        String nextProcessCode = storageBoxCircInfo.getNextProcessCode();
        //查表获取缓冲区的箱子，取第一个，时间排序，先进先出
        List<StorageBoxCircInfo> bufferList = storageLocationMapper.getBufferBoxs(nextProcessCode,2L,0);
        StorageBoxCircInfo bufferCircInfo = new StorageBoxCircInfo();
        if (bufferList.size()!=0){
            bufferCircInfo = bufferList.get(0);
        }else {
            throw new RuntimeException("缓冲区无空箱");
        }
        //调WCS接口
        Long processLocationID = storageBoxCircInfo.getCurrLocationId();
        Location processLocation = locationServiceBiz.getById(processLocationID);
        if (processLocation==null){
            throw new RuntimeException("无库位id对应库位");
        }
        Integer processLocationNo = processLocation.getLocationNumber();
        Long bufferLocationID = bufferCircInfo.getCurrLocationId();
        Location bufferLocation = locationServiceBiz.getById(bufferLocationID);
        if (processLocation==null){
            throw new RuntimeException("无库位id对应库位");
        }
        Integer bufferLocationNo = bufferLocation.getLocationNumber();
        //RGV执行前的插入
        CarTaskExecutionInfo carTaskExecutionInfo = addCarTask(storageBoxCircInfo,bufferCircInfo,processLocation,bufferLocation);
        //调用RGV
        CallRgvEntity callRgvEntity = new CallRgvEntity();
        callRgvEntity.setStartLocationNum(processLocationNo);
        callRgvEntity.setEndLocationNum(bufferLocationNo);
        String returnMsg;
        try {
            returnMsg = callAgv(callRgvEntity);
        }catch (IOException e){
            throw new RuntimeException("RGV异常");
        }
        //RGV执行完的更新
        updateCarTaskExecutionInfo(carTaskExecutionInfo);
        Boolean exChangeResult = exChange(storageBoxCircInfo,bufferCircInfo,1);
        if (!exChangeResult){
            throw new RuntimeException("交换操作失败");
        }
        return Integer.valueOf(returnMsg);
    }

    @Override
    public Integer sendSubToFirstProcess(IdParam idParam) {
        //入口进入第一个缓冲区
//        StorageBoxCircInfo storageBoxCircInfo = storageBoxCircInfoServiceBiz.getById(idParam.getId());
//        String firstProcess = storageBoxCircInfo.getInProcessCode();
//        //查表获取缓冲区的箱子，取第一个，时间排序，先进先出
//        List<StorageBoxCircInfo> bufferList = storageLocationMapper.getBufferBoxs(firstProcess,2L,0);
//        StorageBoxCircInfo bufferCircInfo = new StorageBoxCircInfo();
//        if (bufferList.size()!=0){
//            bufferCircInfo = bufferList.get(0);
//        }else {
//            throw new RuntimeException("缓冲区无空箱位");
//        }
//        //调WCS接口
//        Long processLocationID = storageBoxCircInfo.getCurrLocationId();
//        Integer processLocationNo = getLocationNoByLocationId(processLocationID);
//        Long bufferLocationID = bufferCircInfo.getCurrLocationId();
//        Integer bufferLocationNo = getLocationNoByLocationId(bufferLocationID);
//        CallRgvEntity callRgvEntity = new CallRgvEntity();
//        callRgvEntity.setStartLocationNum(processLocationNo);
//        callRgvEntity.setEndLocationNum(bufferLocationNo);
//        try {
//            String returnMsg = callAgv(callRgvEntity);
//        }catch (IOException e){
//            throw new RuntimeException("调度RGV失败");
//        }
//        //插入基板表，先根据唯一标识获取基板列表
//        Long locationStorageSubID = storageBoxCircInfo.getLocationStorageSubId();
//        QueryWrapper<LocationStorageSub> subQueryWrapper = new QueryWrapper<>();
//        subQueryWrapper.eq(LocationStorageSub.LOCATION_STORAGE_SUB_ID,locationStorageSubID);
//        List<LocationStorageSub> subList = locationStorageSubServiceBiz.list(subQueryWrapper);
//        Long tempLocationStorageSubID = System.currentTimeMillis();
//        for (LocationStorageSub sub : subList){
//            sub.setStatus(0);
//            sub.setCode(String.valueOf(System.currentTimeMillis()));
//            //插入的是库位上的当前编码
//            sub.setLocationStorageSubId(storageBoxCircInfo.getLocationStorageSubId());
//            sub.setLocationId(storageBoxCircInfo.getCurrLocationId());
//            sub.setStorageId(storageBoxCircInfo.getStorageBoxId());
//            sub.setSubType(1);
//            locationStorageSubServiceBiz.save(sub);
//        }
        return 1;
    }

    /*执行两个存储箱的交换操作
        先获取两个库位信息
        存入历史表
        交换存储箱id，是否为空标志
     */
    private boolean exChange(StorageBoxCircInfo processStorageBoxCircInfo,StorageBoxCircInfo bufferStorageBoxCircInfo, Integer subStorageStatus){
        //先存入历史表
        StorageBoxCircInfoHis processStorageBoxCircInfoHis = new StorageBoxCircInfoHis();
        StorageBoxCircInfoHis bufferStorageBoxCircInfoHis = new StorageBoxCircInfoHis();
        BeanUtils.copyProperties(processStorageBoxCircInfo,processStorageBoxCircInfoHis);
        BeanUtils.copyProperties(bufferStorageBoxCircInfo,bufferStorageBoxCircInfoHis);
        //两个都插入历史表
        storageBoxCircInfoHisServiceBiz.save(processStorageBoxCircInfoHis);
        storageBoxCircInfoHisServiceBiz.save(bufferStorageBoxCircInfoHis);
        //交换内容
        Long tempBoxID = processStorageBoxCircInfo.getStorageBoxId();
        String tempBoxCode = processStorageBoxCircInfo.getStorageCode();
        int tempEmpty = processStorageBoxCircInfo.getIsEmpty();
        String tempWorkOrderNo = processStorageBoxCircInfo.getWorkOrderNo();
        processStorageBoxCircInfo.setStorageBoxId(bufferStorageBoxCircInfo.getStorageBoxId());
        processStorageBoxCircInfo.setStorageCode(bufferStorageBoxCircInfo.getStorageCode());
        processStorageBoxCircInfo.setIsEmpty(bufferStorageBoxCircInfo.getIsEmpty());
        processStorageBoxCircInfo.setWorkOrderNo(bufferStorageBoxCircInfo.getWorkOrderNo());
        //setUpdateCommonField(processStorageBoxCircInfo);
        LocalDateTime localDateTime = LocalDateTime.now();
        processStorageBoxCircInfo.setUpdateTime(localDateTime);
        bufferStorageBoxCircInfo.setStorageBoxId(tempBoxID);
        bufferStorageBoxCircInfo.setStorageCode(tempBoxCode);
        bufferStorageBoxCircInfo.setIsEmpty(tempEmpty);
        bufferStorageBoxCircInfo.setWorkOrderNo(tempWorkOrderNo);

        //根据上下片操作决定bufferPort标签
        if (subStorageStatus==1){
            //bufferPort得到workingPort标签
            bufferStorageBoxCircInfo.setLocationStorageSubId(processStorageBoxCircInfo.getLocationStorageSubId());
        }else if (subStorageStatus==2){
            //下片需要生成新标签，防止第二圈开始空箱能查到基板信息
            Long bufferTempLocationStorageSubID = SnowflakeId.getSnowFlakeId();
            bufferStorageBoxCircInfo.setLocationStorageSubId(bufferTempLocationStorageSubID);
        }
        //setUpdateCommonField(bufferStorageBoxCircInfo);
        bufferStorageBoxCircInfo.setUpdateTime(localDateTime);
        //生成新的基板编码，workingPort需要更新标签
        Long tempLocationStorageSubID = SnowflakeId.getSnowFlakeId();
        processStorageBoxCircInfo.setLocationStorageSubId(tempLocationStorageSubID);
        //更新存储箱表
        storageBoxCircInfoServiceBiz.updateById(processStorageBoxCircInfo);
        storageBoxCircInfoServiceBiz.updateById(bufferStorageBoxCircInfo);
        return true;
    }

    private StorageBoxCircInfo getTsbciByLocationNo(IdParam idParam){
        QueryWrapper<Location> locationQueryWrapper = new QueryWrapper<>();
        locationQueryWrapper.eq(Location.LOCATION_NUMBER,idParam.getId());
        Location location = locationServiceBiz.getOne(locationQueryWrapper);
        Long locationId = location.getId();
        QueryWrapper<StorageBoxCircInfo> wrapper = new QueryWrapper<>();
        wrapper.eq(StorageBoxCircInfo.CURR_LOCATION_ID,locationId);
        StorageBoxCircInfo storageBoxCircInfo = storageBoxCircInfoServiceBiz.getOne(wrapper);
        return storageBoxCircInfo;
    }

//    private Integer getLocationNoByLocationId(Long locationID){
//        Location location = locationServiceBiz.getById(locationID);
//        if (location==null){
//            throw new RuntimeException("无库位id对应库位");
//        }
//        return location.getLocationNumber();
//    }

    private CarTaskExecutionInfo addCarTask(StorageBoxCircInfo storageBoxCircInfo,StorageBoxCircInfo bufferCircInfo,Location processLocation,Location bufferLocation){
        CarTaskExecutionInfo carTaskExecutionInfo = new CarTaskExecutionInfo();
        //获取参数
        String code = String.valueOf(SnowflakeId.getSnowFlakeId());
        carTaskExecutionInfo.setInterCode(code);
        carTaskExecutionInfo.setCode(code);
        carTaskExecutionInfo.setTaskId(SnowflakeId.getSnowFlakeId());
        carTaskExecutionInfo.setTaskCode(code);
        String workOrderNo = storageBoxCircInfo.getWorkOrderNo();
        QueryWrapper workOrderWrapper = new QueryWrapper<>();
        workOrderWrapper.eq(WorkOrder.WORK_ORDER_NO,workOrderNo);
        WorkOrder workOrder = workOrderServiceBiz.getOne(workOrderWrapper);
        carTaskExecutionInfo.setWordOrderId(workOrder.getId());
//        carTaskExecutionInfo.setFTaskCode("");
        carTaskExecutionInfo.setFStorageBoxId(storageBoxCircInfo.getStorageBoxId());
        carTaskExecutionInfo.setIsEmpty(storageBoxCircInfo.getIsEmpty());
        carTaskExecutionInfo.setCurrStatus(1);
        carTaskExecutionInfo.setCurrLocationId(processLocation.getId());
        carTaskExecutionInfo.setCurrLocation(processLocation.getLocationName());
        carTaskExecutionInfo.setTargetLocationId(bufferLocation.getId());
        carTaskExecutionInfo.setTargetLocation(bufferLocation.getLocationName());
        carTaskExecutionInfo.setFCurrProcessCode(storageBoxCircInfo.getInProcessCode());
        carTaskExecutionInfo.setFNextProcessCode(bufferCircInfo.getInProcessCode());
        carTaskExecutionInfo.setFStartTime(LocalDateTime.now());
//        carTaskExecutionInfo.setFEndTime(LocalDateTime.now());
        carTaskExecutionInfo.setEquipmentId(1L);
        carTaskExecutionInfo.setFForkCode("1");
//        carTaskExecutionInfo.setWTaskCode("");
        carTaskExecutionInfo.setWStorageBoxId(bufferCircInfo.getStorageBoxId());
        carTaskExecutionInfo.setWIsEmpty(bufferCircInfo.getIsEmpty());
        carTaskExecutionInfo.setWCurrStatus(1);
        carTaskExecutionInfo.setWCurrLocationId(bufferLocation.getId());
        carTaskExecutionInfo.setWCurrLocation(bufferLocation.getLocationName());
        carTaskExecutionInfo.setWTargetLocationId(processLocation.getId());
        carTaskExecutionInfo.setWTargetLocation(processLocation.getLocationName());
        carTaskExecutionInfo.setWCurrProcessCode(bufferCircInfo.getInProcessCode());
        carTaskExecutionInfo.setWNextProcessCode(storageBoxCircInfo.getInProcessCode());
        carTaskExecutionInfo.setWStartTime(LocalDateTime.now());
//        carTaskExecutionInfo.setWEndTime(LocalDateTime.now());
        carTaskExecutionInfo.setWForkCode("1");
        //都是双叉任务
        carTaskExecutionInfo.setTaskType(1);
//        carTaskExecutionInfo.setTaskSource(1);
        carTaskExecutionInfoServiceBiz.save(carTaskExecutionInfo);
        return carTaskExecutionInfo;
    }

    private CarTaskExecutionInfo updateCarTaskExecutionInfo(CarTaskExecutionInfo carTaskExecutionInfo){
        //先插入历史表
        CarTaskExecutionInfoHis carTaskExecutionInfoHis = new CarTaskExecutionInfoHis();
        BeanUtils.copyProperties(carTaskExecutionInfo,carTaskExecutionInfoHis);
        carTaskExecutionInfoHisServiceBiz.save(carTaskExecutionInfoHis);
        //更新数据
        carTaskExecutionInfo.setCurrStatus(2);
        carTaskExecutionInfo.setWCurrStatus(2);
        carTaskExecutionInfo.setFEndTime(LocalDateTime.now());
        carTaskExecutionInfo.setWEndTime(LocalDateTime.now());
        carTaskExecutionInfoServiceBiz.updateById(carTaskExecutionInfo);
        return carTaskExecutionInfo;
    }
}
